package com.wq.concurrency.basic;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Author: wangqiang20995
 * @Date:2018/12/28
 * @Description:
 * @Resource:
 */
public class ThreadInterrupt extends Thread {

    /**
     * https://blog.csdn.net/paincupid/article/details/47626819
     * 引用一篇文章，来自“随心所欲”的《Java的interrupt机制》
     * 当外部线程对某线程调用了thread.interrupt()方法后，java语言的处理机制如下：    
     * 如果该线程处在可中断状态下，（调用了xx.wait()，或者Selector.select(),Thread.sleep()等特定会发生阻塞的api），那么该线程会立即被唤醒，同时会受到一个InterruptedException，同时，如果是阻塞在io上，对应的资源会被关闭。如果该线程接下来不执行“Thread.interrupted()方法（不是interrupt），那么该线程处理任何io资源的时候，都会导致这些资源关闭。当然，解决的办法就是调用一下interrupted()，不过这里需要程序员自行根据代码的逻辑来设定，根据自己的需求确认是否可以直接忽略该中断，还是应该马上退出。
     * 如果该线程处在不可中断状态下，就是没有调用上述api，那么java只是设置一下该线程的interrupt状态，其他事情都不会发生，如果该线程之后会调用行数阻塞API，那到时候线程会马会上跳出，并抛出InterruptedException，接下来的事情就跟第一种状况一致了。如果不会调用阻塞API，那么这个线程就会一直执行下去。除非你就是要实现这样的线程，一般高性能的代码中肯定会有wait()，yield()之类出让cpu的函数，不会发生后者的情况。
     */
    private boolean stop = false;

    public boolean isStop() {
        return stop;
    }

    public void stopTask() {
        this.stop = true;
        interrupt();//改变线程的状态，更新为中断
    }

    @Override
    public void run() {
        try {
            while (!isStop()) {
                System.out.println("sub thread:Hello-->" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            System.out.println("sub thread:task thread interrupted");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            System.out.println("sub thread:task interrupted done");
        } finally {
            System.out.println("sub thread:do something to shutdown");
        }

    }

    public static void main(String args[]) {
        ThreadInterrupt interrupt = new ThreadInterrupt();
        interrupt.start();

        /**
         * 整体流程：
         * 首先是主线程执行到Thread.sleep(10000)，然后进入休眠状态
         * 然后子线程开始执行run方法，休息600毫秒，期间cpu的使用权有分到main，但是main没睡完，就继续给子线程
         * 当main线程睡了10秒之后，进入就绪状态，轮到执行时，先执行stopTask，目的有两个
         *      1.假如子线程正在sleep，那么子线程将抛出InterruptedException,如果cpu时间片没用完，那就继续执行
         *      2.假如子线程刚好sleep完，那么直接while的条件为false，跳出循环，进入finally，之后子线程结束
         * main线程继续往下走，执行join方法（如果子线程还没死，那么子线程执行完，否则main也结束）
         * 只有等到子线程完全执行完了之后，主线程才会继续往下执行[子线程中的catch捕获到异常，并且sleep，但是此时main没有继续往下执行]
         */
        try {
            Thread.sleep(10000);

            System.out.println("main:send shutdown request");
            interrupt.stopTask();
//            Thread.sleep(10000);
            System.out.println("main:make sub thread join to main thread");
            //程序在main线程中调用线程interrupt的join方法，则main线程放弃cpu控制权，并返回interrupt线程继续执行直到线程interrupt执行完毕
            //jdk规定，join(0)的意思不是A线程等待B线程0秒，而是A线程等待B线程无限时间，直到B线程执行完毕，即join(0)等价于join()。
            interrupt.join();//把指定的线程(thread的子类)加入到当前线程;即join(0)等价于join()
            System.out.println("main:main do shutdown after sub thread join done");//
        } catch (InterruptedException e) {
            //捕获主线程在休眠时抛出的InterruptedException
            e.printStackTrace();
        }
    }
}
